#ifndef EJ_BSP_IIC_H
#define EJ_BSP_IIC_H

#include "common_def.h"

/*-------------------------------- Type Definitions -----------------------------*/

typedef enum {
    I2C_OK,                 ///< Operation succeeded
    I2C_ERR_NACK,           ///< NACK received from device
    I2C_ERR_TIMEOUT,        ///< Communication timeout (software mode only)
    I2C_ERR_INVALID_CFG,    ///< Invalid configuration (e.g., NULL pointers)
    I2C_ERR_BUS_NOT_FOUND,  ///< Specified bus name not registered
    I2C_ERR_DEVICE_EXISTS,  ///< Device name already registered
    I2C_ERR_BUS_NOT_INIT,    ///< Bus not initialized
    I2C_ERR_DEVICE_NOT_FOUND,
    I2C_ERR_NOT_PARAM,
} i2c_status_t;


typedef enum {
    I2C_MODE_SW,    ///< Software (bit-banged) I2C
    I2C_MODE_HW     ///< Hardware peripheral-based I2C
} i2c_mode_t;

typedef struct 
{
    // GPIO Control Functions
    void (*gpio_init)(void);    ///< Set SCL pin level (0/1)
    void (*scl_set)(uint8_t val);    ///< Set SCL pin level (0/1)
    void (*sda_set)(uint8_t val);    ///< Set SDA pin level (0/1)
    void (*sda_dir)(uint8_t input);  ///< Set SDA direction (0=output, 1=input)
    uint8_t (*sda_read)(void);      ///< Read SDA pin level

    // Timing Control
    void (*delay_us)(uint16_t us);   ///< Microsecond delay function
    uint16_t clock_delay;           ///< Clock pulse width in microseconds
} sw_i2c_cfg_t;

typedef struct 
{
    void (*init)(void *hw_instance);                         ///< Initialize hardware
    i2c_status_t (*write)(void *hw_instance, uint8_t addr,   ///< Write data to device
                         const uint8_t *buf, uint16_t len, uint32_t timeout_ms);
    i2c_status_t (*read)(void *hw_instance, uint8_t addr,    ///< Read data from device
                        uint8_t *buf, uint16_t len, uint32_t timeout_ms);

	i2c_status_t (*write_read)(void *hw_instance, uint8_t addr,
                              const uint8_t *tx_buf, uint16_t tx_len,
                              uint8_t *rx_buf, uint16_t rx_len,
                              uint32_t timeout_ms);
} hw_i2c_ops_t;


typedef struct {
    void *hw_instance;
    hw_i2c_ops_t ops;
} hw_i2c_cfg_t;


typedef struct {
    i2c_mode_t mode;
    union {
        sw_i2c_cfg_t sw;
        hw_i2c_cfg_t hw;
    } cfg;
} i2c_drv_info_t;

typedef struct 
{
    const char *bus_name;       
    i2c_drv_info_t drv_info;   
    bool initialized;          
} i2c_bus_t;

typedef struct 
{
    const char *dev_name;       
    const char *bus_name;      
    uint8_t address;          
} i2c_device_t;

/* For low-level driver. */
i2c_status_t ej_bsp_i2c_register_bus(const char *bus_name, const i2c_drv_info_t *drv_info);
i2c_status_t ej_bsp_i2c_init_bus(const char *bus_name);

/* For high-level code. */
i2c_status_t ej_bsp_i2c_attach_device(const char *bus_name, const char *dev_name, uint8_t address);
i2c_status_t ej_bsp_i2c_write_to_device(const char *dev_name, const uint8_t *data, uint16_t len, uint32_t timeout_ms);
i2c_status_t ej_bsp_i2c_read_from_device(const char *dev_name, uint8_t *buf, uint16_t len, uint32_t timeout_ms);
i2c_status_t ej_bsp_i2c_write_read(const char *dev_name, const uint8_t *cmd, uint16_t cmd_len, uint8_t *resp, uint16_t resp_len, uint32_t timeout_ms);

/* Expand API */
i2c_status_t ej_bsp_i2c_reg_write_byte(const char *dev_name, uint8_t reg, uint8_t value, uint32_t timeout_ms);
i2c_status_t ej_bsp_i2c_reg_read_byte(const char *dev_name, uint8_t reg, uint8_t *value, uint32_t timeout_ms);
i2c_status_t ej_bsp_i2c_reg_write_burst(const char *dev_name, uint8_t reg, const uint8_t *data, uint16_t len, uint32_t timeout_ms);
i2c_status_t ej_bsp_i2c_reg_read_burst(const char *dev_name, uint8_t reg, uint8_t *data, uint16_t len, uint32_t timeout_ms);
i2c_status_t ej_bsp_i2c_probe_device(const char *dev_name, uint32_t timeout_ms);


#endif // EJ_BSP_IIC_H